/*
 * Copyright (c) 2001, 2002 Boris Pruessmann and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v0.5 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v05.html
 *
 * Contributors: Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.perforce.core.internal.api;

import com.google.common.collect.Lists;

import net.sourceforge.perforce.api.IPerforceCommand;
import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.api.ILogEntry;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.internal.Policy;
import net.sourceforge.perforce.core.resources.RemoteFile;
import net.sourceforge.perforce.core.syncinfo.ResourceSyncInfo;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.PlatformObject;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @version $Revision: 489 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris Pr??mann</a>
 */
public class Filelog extends AbstractPerforceCommand implements IPerforceCommand {
  // ---------------------------------------------------------------------------
  // Private Variables

  /** Stores the result of the operation. */
  private List<Result> results = Lists.newArrayList();
  /** Stores the progress monitor. */
  private IProgressMonitor monitor;
  /**
   * Stores the responsible perforce server. TODO: Remove
   */
  private IPerforceServer perforceServer;

  // --------------------------------------------------------------- Public
  // Static Factory Methods

  /**
   * Convenience method for creating instances of Filelog.
   *
   * @param server the responsible perforce server.
   * @param monitor used for progress feedback.
   * @return the new Filelog instance.
   */
  public static final Filelog newInstance(IPerforceServer server, IProgressMonitor monitor) {
    MultiStatus status =
        new MultiStatus(PerforceCorePlugin.ID, IStatus.OK, Policy.bind("Command.executingError",
            "p4 filelog"), null);

    return new Filelog(status, server, monitor);
  }

  // ------------------------------------------------------------------------
  // Private Constructors

  /**
   * Creates a new instance.
   *
   * @param status the MultiStatus instance.
   * @param perforceServer the responsible server.
   * @param monitor used of progress feedback.
   */
  private Filelog(MultiStatus status, IPerforceServer perforceServer, IProgressMonitor monitor) {
    super(status);
    this.monitor = monitor;
    this.perforceServer = perforceServer;
  }

  // -------------------------------------------------------- Public Methods
  // (IClientUserDelegate)

  @Override
  public void outputStat(Map<String, ?> strDict) {
    for (int no = 0; strDict.containsKey("rev" + no); no++) //$NON-NLS-1$
    {
      Result result = new Result();
      result.setPerforceServer(perforceServer);
      result.setDepotFilename(Helper.safeGetString(strDict, "depotFile")); //$NON-NLS-1$
      result.setRevision(Helper.safeGetInteger(strDict, "rev" + no)); //$NON-NLS-1$
      result.setChangelist(Helper.safeGetChangelist(strDict, "change" + no)); //$NON-NLS-1$
      result.setType(Helper.safeGetString(strDict, "type" + no)); //$NON-NLS-1$
      result.setTime(Helper.safeGetDate(strDict, "time" + no)); //$NON-NLS-1$
      result.setUser(Helper.safeGetString(strDict, "user" + no)); //$NON-NLS-1$
      result.setClient(Helper.safeGetString(strDict, "client" + no)); //$NON-NLS-1$
      result.setDescription(Helper.safeGetString(strDict, "desc" + no)); //$NON-NLS-1$


      List<String> actions = Lists.newArrayList();
      actions.add(Helper.safeGetString(strDict, "action" + no)); //$NON-NLS-1$

      for (int i = 0; strDict.containsKey("how" + no + "," + i); i++) //$NON-NLS-1$ //$NON-NLS-2$
      {
        StringBuilder buffer = new StringBuilder();
        buffer.append(Helper.safeGetString(strDict, "how" + no + "," + i)); //$NON-NLS-1$ //$NON-NLS-2$

        buffer.append(" "); //$NON-NLS-1$
        buffer.append(Helper.safeGetString(strDict, "file" + no + "," + i)); //$NON-NLS-1$ //$NON-NLS-2$

        buffer.append(" "); //$NON-NLS-1$
        buffer.append(Helper.safeGetString(strDict, "srev" + no + "," + i)); //$NON-NLS-1$ //$NON-NLS-2$

        buffer.append(" "); //$NON-NLS-1$
        buffer.append(Helper.safeGetString(strDict, "erev" + no + "," + i)); //$NON-NLS-1$ //$NON-NLS-2$

        actions.add(buffer.toString());
      }

      result.setActions(actions.toArray(new String[actions.size()]));
      results.add(result);

      monitor.worked(1);
    }
  }

  // ----------------------------------------------------------- Public Methods
  // (IPerforceCommand)

  @Override
  public IStatus getStatus() {
    return getMultiStatus();
  }

  public String getCommand() {
    return "filelog"; //$NON-NLS-1$
  }

  //----------------------------------------------------------------------------
  // -- Public Methods

  /**
   * Returns the result of the operation.
   *
   * @return array of result objects.
   */
  public ILogEntry[] getResult() {
    return results.toArray(new ILogEntry[results.size()]);
  }

  // ----------------------------------------------------------------------
  // Private Nested Classes

  /**
   * Implementation of the ILogEntry interface. Returned as result of the
   * operation.
   *
   * TODO: Remove PlatformObject dependency.
   */
  public static class Result extends PlatformObject implements ILogEntry {
    // -----------------------------------------------------------------------
    // Private Variables

    /** Stores a reference to the remote file / version. */
    private RemoteFile file;
    /** Stores the name of the file. */
    private String depotFilename;
    /** Stores the revision number. */
    private Integer revision;
    /** Stores the creating changelist. */
    private Integer changelist;
    /** Stores the action that lead to the revision. */
    private String[] actions;
    /** Stores the filetype. */
    private String type;
    /** Stores the submission date. */
    private Date time;
    /** Stores the user name. */
    private String user;
    /** Stores the client name. */
    private String client;
    /** Stores the description. */
    private String description;
    /**
     * Stores the perforce server. TODO: Remove
     */
    private IPerforceServer perforceServer;

    //--------------------------------------------------------------------------
    // Public Methods

    /** @see ILogEntry#getDepotFilename() */
    public String getDepotFilename() {
      return depotFilename;
    }

    /** @see ILogEntry#getRevision() */
    public Integer getRevision() {
      return revision;
    }

    /** @see ILogEntry#getChangelist() */
    public Integer getChangelist() {
      return changelist;
    }

    /** @see ILogEntry#getActions() */
    public String[] getActions() {
      return actions;
    }

    /** @see ILogEntry#getType() */
    public String getType() {
      return type;
    }

    /** @see ILogEntry#getTime() */
    public Date getTime() {
      return time;
    }

    /** @see ILogEntry#getUser() */
    public String getUser() {
      return user;
    }

    /** @see ILogEntry#getClient() */
    public String getClient() {
      return client;
    }

    /** @see ILogEntry#getDescription() */
    public String getDescription() {
      return description;
    }

    /** @see ILogEntry#getRemoteFile() */
    public RemoteFile getRemoteFile() {
      if (file == null) {
        file = new RemoteFile(perforceServer, depotFilename, "#" + revision.intValue());
      }

      return file;
    }

    /** @see ILogEntry#isDeleted() */
    public boolean isDeleted() {
      return actions[0].equals(ResourceSyncInfo.ACTION_DELETE);
    }

    //--------------------------------------------------------------------------
    // ------- Methods

    /**
     * Sets the actions.
     *
     * @param actions The actions to set
     */
    void setActions(String[] actions) {
      this.actions = actions;
    }

    /**
     * Sets the changelist.
     *
     * @param changelist The changelist to set
     */
    void setChangelist(Integer changelist) {
      this.changelist = changelist;
    }

    /**
     * Sets the client.
     *
     * @param client The client to set
     */
    void setClient(String client) {
      this.client = client;
    }

    /**
     * Sets the depotFilename.
     *
     * @param depotFilename The depotFilename to set
     */
    void setDepotFilename(String depotFilename) {
      this.depotFilename = depotFilename;
    }

    /**
     * Sets the description.
     *
     * @param description The description to set
     */
    void setDescription(String description) {
      this.description = description;
    }

    /**
     * Sets the perforceServer.
     *
     * @param perforceServer The perforceServer to set
     */
    void setPerforceServer(IPerforceServer perforceServer) {
      this.perforceServer = perforceServer;
    }

    /**
     * Sets the revision.
     *
     * @param revision The revision to set
     */
    void setRevision(Integer revision) {
      this.revision = revision;
    }

    /**
     * Sets the time.
     *
     * @param time The time to set
     */
    void setTime(Date time) {
      this.time = time;
    }

    /**
     * Sets the type.
     *
     * @param type The type to set
     */
    void setType(String type) {
      this.type = type;
    }

    /**
     * Sets the user.
     *
     * @param user The user to set
     */
    void setUser(String user) {
      this.user = user;
    }
  }
}
